using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace FBPChaos
{
	/// <summary>
	/// Controls game logic
	/// </summary>
    public class Game
	{
        const string monstersFileName = "monsters.txt";
        const string spellsFileName = "spells.txt";
        int activeWizard;
		int lawChaosIndicator;
		int numberOfWizards;
        int numberOfPlayers;
        int difficulty;
        int turnNumber;
        Wizard[] wizards;
        List<Monster> monsters;
        MainMenu mainMenu;
        ShowText messages;
        Cursor cursor;
        List<Spell> availableSpells;
        List<Monster> availableMonsters;  //default attributes for monsters  -?? need copy constructor ??
                
        const int MaxWizards = 8;
        const int MaxDifficulty = 5;
        const int GridWidth = 15;
        const int GridHeight = 12;

        GameStatus status;

        enum GameStatus 
        { 
            Intitialising = 0, 
            StartGame = 1,
            WizardNumber = 2,
            PlayerNumber = 3,
            DifficultyLevel = 4,
         // StartTurns =5,
            CastingPhase = 10,
            SpellList = 11,
            CastSpell = 12,
            MovementPhase = 15,
            EndTurnProcess = 20,
            EndGame = 99
        };

        public Game()
        {        
            turnNumber = 0;
            activeWizard = 0;
            lawChaosIndicator = 0;
            messages = new ShowText();
            mainMenu = new MainMenu();
            status = GameStatus.Intitialising;
            cursor = new Cursor(GridHeight, GridWidth);
            availableMonsters = new List<Monster>();
            availableSpells = new List<Spell>();
            loadMonsters();
            loadSpells();
        }

        private void loadMonsters()
        {
            string[] data = ReadData.readLines(monstersFileName);
            if(data != null)
            {
                int counter = 0;
                foreach (string line in data)
                {
                    availableMonsters.Add(new Monster(line));
                    Console.WriteLine(availableMonsters[counter].MonsterName);
                    messages.addText(availableMonsters[counter].MonsterName);
                    counter++;
                }
            }
        }

        private void loadSpells()
        {
            string[] data = ReadData.readLines(spellsFileName);
            if (data != null)
            {
                int counter = 0;
                foreach (string line in data)
                {
                    availableSpells.Add(new Spell(line, availableMonsters));
                    messages.addText(availableSpells[counter].Name);
                    counter++;
                }
            }
        }
        
        private void endGame()
		{

            status = GameStatus.EndGame;
		}

		public void startGame()
		{
            turnNumber = 0;
            activeWizard = 0;
            mainMenu.newGame();
            status = GameStatus.StartGame;
        }

        public void nextStep(Keys[] keysPressed)
        {
            switch (status)
            {
                case GameStatus.Intitialising:
                    //do nothing
                    break;
                case GameStatus.StartGame:
                    mainMenu.showWizardsQuery(MaxWizards);
                    status = GameStatus.WizardNumber;
                    break;
                case GameStatus.WizardNumber:
                    //get input
                    int numberPressed;
                    numberPressed = InputHelper.GetNumberKey(keysPressed);
                    if (numberPressed > 1 && numberPressed <= MaxWizards)
                    {
                        numberOfWizards = numberPressed;
                        messages.addText( numberOfWizards.ToString());
                        mainMenu.showPlayersQuery(numberOfWizards);
                        status = GameStatus.PlayerNumber;
                    }
                    break;
                case GameStatus.PlayerNumber:
                    int playerNumberPressed;
                    playerNumberPressed = InputHelper.GetNumberKey(keysPressed);
                    if (playerNumberPressed > 0 && playerNumberPressed <= numberOfWizards)
                    {
                        numberOfPlayers = playerNumberPressed;
                        messages.addText(numberOfWizards.ToString());
                        mainMenu.showDifficultyQuery(MaxDifficulty);
                        status = GameStatus.DifficultyLevel;
                    }
                    break;
                case GameStatus.DifficultyLevel:
                    int difficultyNumberPressed;
                    difficultyNumberPressed = InputHelper.GetNumberKey(keysPressed);
                    if (difficultyNumberPressed > 0 && difficultyNumberPressed <= MaxDifficulty)
                    {
                        difficulty = difficultyNumberPressed;
                        messages.addText(difficultyNumberPressed.ToString());
                        
           //             status = GameStatus.StartTurns;
                        setupWizards();
                        positionWizards();
                        //messages.addText("hiding menu");
                        mainMenu.hideMenu();
                        startTurns();
                    }
                    break;
                case GameStatus.CastingPhase:
                    
                    if (mainMenu.Active)
                    {
                        int numberKey = InputHelper.GetNumberKey(keysPressed);
                        if (numberKey == 1)
                        {
                            mainMenu.showSpellList(wizards[activeWizard].listSpells());
                            messages.addText(wizards[activeWizard].listSpells().Length.ToString());
                            status = GameStatus.SpellList;
                        }
                        else if (numberKey == 2)
                            mainMenu.hideMenu();
                    }
                    else if(InputHelper.menuKeyPressed(keysPressed))
                    {
                        mainMenu.showPlayerOptions();
                        status = GameStatus.CastingPhase;
                    }
                    else if (InputHelper.EnterKeyPressed(keysPressed))
                    {
                        nextWizard();
                    }
                    break;
                case GameStatus.SpellList:
                    if (InputHelper.menuKeyPressed(keysPressed))
                    {
                        mainMenu.showPlayerOptions();
                        status = GameStatus.CastingPhase;
                    }
                    else if (InputHelper.spellKeyPressed(keysPressed, availableSpells.Count ))
                    {
                        Console.WriteLine("Spell selected");
                        mainMenu.hideMenu();
                        cursor.Position = wizards[activeWizard].Position;
                        cursor.show();
                        status = GameStatus.CastSpell;
                    }
                    break;
                case GameStatus.CastSpell:
                    switch (InputHelper.cursorKey(keysPressed))
                    {
                        case Direction.Up:
                            cursor.moveCursorUp();
                            break;
                        case Direction.Down:
                            cursor.moveCursorDown();
                            break;
                        case Direction.Left:
                            cursor.moveCursorLeft();
                            break;
                        case Direction.Right:
                            cursor.moveCursorRight();
                            break;
                        case Direction.Select:
                            cursor.Position;
                            break;
                        default:
                            //do nothing - neither arrow key nor select key pressed
                            break;
                    }
                    break;
                case GameStatus.MovementPhase:
                    if (InputHelper.EnterKeyPressed(keysPressed))
                    {
                        nextWizard();
                    }
                    break;
                default:
                    //do nothing
                    break;
            }
            
        }

        private void setupWizards()
        {
            wizards = new Wizard[numberOfWizards];
            for (int counter = 0; counter < numberOfWizards; counter++ )
            {
                //messages.addText("setting up wizard " + counter);
                wizards[counter] = new Wizard(new Point(1, 1), availableSpells);
                wizards[counter].Colour = Color.Red;
            }
        }

        private void positionWizards()
        {
            switch (numberOfWizards)
            {
                /*  2 Wizards x equals 1 and 15, y equals 6 and 6
    		        3 Wizards x equals 1, 15 and 8, y equals 1, 1 and 12
	    	        4 Wizards x equals 1, 15, 1 and 15, y equals 1, 1, 12 and 12
		            5 Wizards x equals 1, 5, 15, 1 and 15, y equals 1, 1, 1, 12 and 12
    		        6 Wizards x equals 1, 8, 15, 1, 8 and 15, y equals 1, 1, 1, 12, 12 and 12
	    	        7 Wizards x equals 1, 8, 15, 1, 1, 8 and 15, y equals 1, 1, 1, 6, 12, 12 and 12
		            8 Wizards x equals 1,8,15,1,15,1,8 and 15, y equals 1,1,1,6 ,6,12,12 and 12
                 */
                case 2:
                    wizards[0].Position = new Point(1, 6);
                    wizards[1].Position = new Point(15, 6);
                    break;
                case 3:
                    wizards[0].Position = new Point(1, 1);
                    wizards[1].Position = new Point(15, 1);
                    wizards[2].Position = new Point(8, 12);
                    break;
                case 4:
                    wizards[0].Position = new Point(1, 1);
                    wizards[1].Position = new Point(15, 1);
                    wizards[2].Position = new Point(1, 12);
                    wizards[3].Position = new Point(15, 12);
                    break;
                case 5:
                    wizards[0].Position = new Point(1, 1);
                    wizards[1].Position = new Point(8, 1);
                    wizards[2].Position = new Point(15, 1);
                    wizards[3].Position = new Point(1, 12);
                    wizards[4].Position = new Point(15, 12);
                    break;
                case 6:
                    wizards[0].Position = new Point(1, 1);
                    wizards[1].Position = new Point(8, 1);
                    wizards[2].Position = new Point(15, 1);
                    wizards[3].Position = new Point(1, 12);
                    wizards[4].Position = new Point(8, 12);
                    wizards[5].Position = new Point(15, 12);
                    break;
                case 7:
                    wizards[0].Position = new Point(1, 1);
                    wizards[1].Position = new Point(8, 1);
                    wizards[2].Position = new Point(15, 1);
                    wizards[3].Position = new Point(1, 6);
                    wizards[4].Position = new Point(1, 12);
                    wizards[5].Position = new Point(8, 12);
                    wizards[6].Position = new Point(15, 12);
                    break;
                case 8:
                    wizards[0].Position = new Point(1, 1);
                    wizards[1].Position = new Point(8, 1);
                    wizards[2].Position = new Point(15, 1);
                    wizards[3].Position = new Point(1, 6);
                    wizards[4].Position = new Point(15, 6);
                    wizards[5].Position = new Point(1, 12);
                    wizards[6].Position = new Point(8, 12);
                    wizards[7].Position = new Point(15, 12);
                    break;
                default:
                    break;
            }
        }

        private void startTurns()
        {
            turnNumber++;
            status = GameStatus.CastingPhase;
            mainMenu.showPlayerOptions();
        }

        private void endTurn()
        {
            //check to see if winner

                       
            
            //blobs, fire etc, new spells

            //next turn
            turnNumber++;
            status = GameStatus.SpellList;
            

        }

        private void nextWizard()
        {
            do
            {
                activeWizard++;
                messages.addText(activeWizard.ToString());
            }
            while (activeWizard < numberOfWizards && !wizards[activeWizard].Alive);
            if (activeWizard >= numberOfWizards)
            {
                activeWizard = 0;
                endPhase();
            }
            else
            {
                mainMenu.showPlayerOptions();
                status = GameStatus.CastingPhase;
            }
        }

        private void endPhase()
        {
            if (status == GameStatus.CastingPhase)
            {
                status = GameStatus.MovementPhase;
            }
            else
            {
                status = GameStatus.EndTurnProcess;
                endTurn();
            }
        }


        public Wizard[] Wizards
        {
            get { return wizards; }
        }

        public List<Monster> Monsters
        {
            get { return monsters; }
        }

        public Cursor GameCursor
        {
            get { return cursor; }
        }

        public ShowText Messages
        {
            get { return messages; }
        }

        public MainMenu Menu
        {
            get { return mainMenu; }
        }
	}
}
